package fr.sportcom.sportcom.controller;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONArray;
import org.json.JSONObject;

import fr.sportcom.sportcom.R;
import fr.sportcom.sportcom.SportComApplication;
import fr.sportcom.sportcom.adapter.FriendListAdapter;
import fr.sportcom.sportcom.model.AdsManager;
import fr.sportcom.sportcom.model.CustomHttpClient;
import fr.sportcom.sportcom.model.User;

import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AutoCompleteTextView;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.ArrayAdapter;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.Toast;

public class FriendListActivity extends Activity 
implements OnCheckedChangeListener, OnItemClickListener, View.OnClickListener, TextWatcher {

	//// EXTRA
	// En entr�e :
	public final static String EXTRA_ACTION = "fr.sportcom.sportcom.extra.fla.ACTION";
	public final static String EXTRA_EVENT = "fr.sportcom.sportcom.extra.fla.EVENT";
	// Valeur d'ACCTION:
	public final static int VIEW = 1, INVITE = 2;
	
	private static final int THRESHOLD = 4;

	private int pAction;
	private Integer selectedEvent;
	
	private ListView listView;
	private LinearLayout barAction;
	private ImageButton btnAdd;
	private ImageButton btnDel;
	private ImageButton btnInvite;
	private View mloadingStatusView;
	
	private RefreshListTask mRefresh;
	private AddFriendTask mAdd;
	private DelFriendTask mDel;
	private InviteFriendTask mInvite;

	private RefreshNameAutocompTask mListNameAutocompTask = null;
	private ArrayAdapter<String> autoCompleteAdapter;
	private AutoCompleteTextView mAddFriendView;
	private AlertDialog mConfirm = null;

	private int pUserId = 0;
	private ArrayList<User> lUser = new ArrayList<User>();
	private ArrayList<Integer> selectedUser = new ArrayList<Integer>();

	public static Intent prepareIntent(Context context, int action, Integer eventId) {
		return new Intent(context, FriendListActivity.class)
		.putExtra(EXTRA_ACTION, action)
		.putExtra(EXTRA_EVENT, eventId);
	}
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		//setContentView(R.layout.activity_friend_list);
		setContentView(R.layout.sponso_layout);
		View appContent = LayoutInflater.from(this).inflate(
				R.layout.activity_friend_list, 
				(ViewGroup) this.findViewById(R.id.app_content), 
				false);
		((LinearLayout)this.findViewById(R.id.app_content)).addView(appContent);
		AdsManager.displayAds(this);

		// On r�cup�re l'intent
		Intent i = getIntent();
		pAction = i.getIntExtra(EXTRA_ACTION, VIEW);
		selectedEvent = i.getIntExtra(EXTRA_EVENT, 0);

		// On r�cup�re le userId
		pUserId = ((SportComApplication) (this.getApplication())).getLoggedUser().getId();

		listView = (ListView) findViewById(R.id.listfriend);
		mloadingStatusView = findViewById(R.id.loading_status_event);
		barAction = (LinearLayout) findViewById(R.id.action_bar);
		btnAdd = (ImageButton) findViewById(R.id.btn_add);
		btnDel = (ImageButton) findViewById(R.id.btn_del);
		btnInvite = (ImageButton) findViewById(R.id.btn_invite);
		
		btnAdd.setOnClickListener(this);
		btnDel.setOnClickListener(this);
		btnInvite.setOnClickListener(this);

		mAddFriendView = new AutoCompleteTextView(this);
		// Init autoComplete
		mAddFriendView.addTextChangedListener(this);
		mAddFriendView.setThreshold(THRESHOLD);
		// Son adapter
		autoCompleteAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line, new ArrayList<String>());
		autoCompleteAdapter.setNotifyOnChange(false);
		mAddFriendView.setAdapter(autoCompleteAdapter);
		
		// On adapte selon l'action
		if(pAction == INVITE) {
			btnInvite.setVisibility(View.VISIBLE);
		}
		
		refreshUserList();
	}
	
	@Override
	protected void onResume() {
		super.onResume();
		AdsManager.displayAds(this);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.friend_list, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case android.R.id.home:
			// This ID represents the Home or Up button. In the case of this
			// activity, the Up button is shown. Use NavUtils to allow users
			// to navigate up one level in the application structure. For
			// more details, see the Navigation pattern on Android Design:
			//
			// http://developer.android.com/design/patterns/navigation.html#up-vs-back
			//
			//NavUtils.navigateUpFromSameTask(this);
			this.finish();
			return true;
		}
		return super.onOptionsItemSelected(item);
	}

	public void refreshUserList() {
		if (mRefresh != null) {
			return;
		}

		showProgress(true);
		mRefresh = new RefreshListTask();
		mRefresh.link(this);
		mRefresh.execute();
	}
	
	private void showProgress(final boolean show) {
		// On Honeycomb MR2 we have the ViewPropertyAnimator APIs, which allow
		// for very easy animations. If available, use these APIs to fade-in
		// the progress spinner.
		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
			int shortAnimTime = getResources().getInteger(
					android.R.integer.config_shortAnimTime);

			mloadingStatusView.setVisibility(View.VISIBLE);
			mloadingStatusView.animate().setDuration(shortAnimTime)
			.alpha(show ? 1 : 0)
			.setListener(new AnimatorListenerAdapter() {
				@Override
				public void onAnimationEnd(Animator animation) {
					mloadingStatusView.setVisibility(show ? View.VISIBLE
							: View.GONE);
				}
			});

			listView.setVisibility(View.VISIBLE);
			listView.animate().setDuration(shortAnimTime)
			.alpha(show ? 0 : 1)
			.setListener(new AnimatorListenerAdapter() {
				@Override
				public void onAnimationEnd(Animator animation) {
					listView.setVisibility(show ? View.GONE
							: View.VISIBLE);
				}
			});
		} else {
			// The ViewPropertyAnimator APIs are not available, so simply show
			// and hide the relevant UI components.
			mloadingStatusView.setVisibility(show ? View.VISIBLE : View.GONE);
			listView.setVisibility(show ? View.GONE : View.VISIBLE);
		}
	}
	
	private class RefreshListTask extends AsyncTask<Void, Void, Boolean> {

		private WeakReference<FriendListActivity> mActivity = null;
		private int backStatus = -99;

		@Override
		protected Boolean doInBackground(Void... params) {

			CustomHttpClient request = new CustomHttpClient();
			JSONObject jObj = null;
			ArrayList<NameValuePair> param = new ArrayList<NameValuePair>();
			param.add(new BasicNameValuePair("userId", ""+pUserId));
			try {
				jObj = request.postData("loadFriendList", param);
				backStatus = jObj.getInt("back");

				if(backStatus != 0) {
					return false;
				}

				lUser.clear();
				JSONArray list = jObj.getJSONArray("list");
				for(int i=0; i<list.length(); i++) {
					User user = new User(list.getJSONObject(i).getInt("uti_id"), 
							list.getJSONObject(i).getString("uti_email"), 
							list.getJSONObject(i).getString("uti_prenom"), 
							list.getJSONObject(i).getString("uti_nom"), 
							list.getJSONObject(i).getString("uti_naissance"),
							list.getJSONObject(i).getString("uti_ville")
							);
					lUser.add(user);
				}

			} catch (Exception e) {
				return false;
			}

			return true;
		}

		@Override
		protected void onPostExecute(final Boolean success) {
			mRefresh = null;
			
			if (!success) {
				Toast.makeText(mActivity.get(), "Une erreur est survenue. "+backStatus, Toast.LENGTH_LONG).show();
			}

			FriendListAdapter adapt = new FriendListAdapter(mActivity.get(), lUser);

			listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
			listView.setAdapter(adapt);

			listView.setOnItemClickListener(mActivity.get());

			showProgress(false);
		}

		public void link (FriendListActivity pActivity) {
			mActivity = new WeakReference<FriendListActivity>(pActivity);
		}
	}
	
	@Override
	public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
		Integer userId = Integer.parseInt((String) buttonView.getTag());
        if(isChecked){
        	selectedUser.add(userId);
        }
        else {
        	selectedUser.remove(userId);
        }
        barAction.setVisibility(selectedUser.isEmpty() ? View.GONE : View.VISIBLE);
	}

	@Override
	public void onItemClick(AdapterView<?> parent, View view, int pos, long id) {
		((CheckBox)view.findViewById(R.id.check)).performClick();
	}

	@Override
	public void onClick(View v) {
		switch(v.getId()) {
		case R.id.btn_add:
			if (mAdd == null) {
				mAddFriendView.setText("");
				if(mConfirm == null) {
					mConfirm = new AlertDialog.Builder(this)
					    .setTitle(R.string.add_friend_title)
					    .setView(mAddFriendView)
					    .setPositiveButton(R.string.invite, new DialogInterface.OnClickListener() {
					        public void onClick(DialogInterface dialog, int whichButton) {
								showProgress(true);
								mAdd = new AddFriendTask(FriendListActivity.this);
								mAdd.execute(mAddFriendView.getText().toString());
					        }
					    }).setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
					        public void onClick(DialogInterface dialog, int whichButton) {
					            // Do nothing.
					        }
					    })
					    .show();
				}
				else {
					mConfirm.show();
				}
			}
			break;
		case R.id.btn_del:
			if (mDel == null) {
				AlertDialog.Builder confirm = new AlertDialog.Builder(this)
				    .setTitle(R.string.confirmation)
				    .setMessage(R.string.msg_delete)
				    .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
				        public void onClick(DialogInterface dialog, int whichButton) {
							showProgress(true);
							mDel = new DelFriendTask(FriendListActivity.this);
							Integer[] arr = selectedUser.toArray(new Integer[0]);
							mDel.execute(arr);
				        }
				    }).setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
				        public void onClick(DialogInterface dialog, int whichButton) {
				            // Do nothing.
				        }
				    });
				confirm.show();
			}
			break;
		case R.id.btn_invite:
			if (mInvite == null) {
				showProgress(true);
				mInvite = new InviteFriendTask(FriendListActivity.this);
				Integer[] arr = selectedUser.toArray(new Integer[0]);
				mInvite.execute(arr);
			}
		}
	}
	
	/*private class AddFriendTask extends AsyncTask<Integer, Void, Boolean> {

		private WeakReference<FriendListActivity> mActivity = null;
		
		public AddFriendTask(FriendListActivity pActivity) {
			link(pActivity);
		}
		
		@Override
		protected Boolean doInBackground(Integer... friendId) {
			CustomHttpClient request = new CustomHttpClient();
			JSONObject jObj = null;
			ArrayList<NameValuePair> param = new ArrayList<NameValuePair>();
			param.add(new BasicNameValuePair("userId", ""+pUserId));
			for (Integer fId : friendId) {
				param.add(new BasicNameValuePair("friendId[]", ""+fId));
			}

			try {
				jObj = request.postData("addFriend", param);

				if(jObj.getInt("back") != 0) {
					return false;
				}

			} catch (Exception e) {
				return false;
			}

			return true;
		}

		@Override
		protected void onPostExecute(final Boolean success) {
			mDel = null;
			if (mActivity.get() != null) {
				showProgress(false);
				if (!success) {
					Toast.makeText(mActivity.get(), "Une erreur est survenue.", Toast.LENGTH_LONG).show();
					return;
				}
				mActivity.get().refreshUserList();
			}
		}
		
		public void link(FriendListActivity pActivity) {
			mActivity = new WeakReference<FriendListActivity>(pActivity);
		}
	}*/
	private class AddFriendTask extends AsyncTask<String, Void, Boolean> {

		private WeakReference<FriendListActivity> mActivity = null;
		
		public AddFriendTask(FriendListActivity pActivity) {
			link(pActivity);
		}
		
		@Override
		protected Boolean doInBackground(String... friendName) {
			CustomHttpClient request = new CustomHttpClient();
			JSONObject jObj = null;
			ArrayList<NameValuePair> param = new ArrayList<NameValuePair>();
			param.add(new BasicNameValuePair("userId", ""+pUserId));
			for (String fName : friendName) {
				param.add(new BasicNameValuePair("friendName[]", fName));
			}

			try {
				jObj = request.postData("addFriendName", param);

				if(jObj.getInt("back") != 0) {
					return false;
				}

			} catch (Exception e) {
				return false;
			}

			return true;
		}

		@Override
		protected void onPostExecute(final Boolean success) {
			mAdd = null;
			if (mActivity.get() != null) {
				showProgress(false);
				if (!success) {
					Toast.makeText(mActivity.get(), "Une erreur est survenue.", Toast.LENGTH_LONG).show();
					return;
				}
				mActivity.get().refreshUserList();
			}
		}
		
		public void link(FriendListActivity pActivity) {
			mActivity = new WeakReference<FriendListActivity>(pActivity);
		}
	}
	
	private class DelFriendTask extends AsyncTask<Integer, Void, Boolean> {

		private WeakReference<FriendListActivity> mActivity = null;
		
		public DelFriendTask(FriendListActivity pActivity) {
			link(pActivity);
		}
		
		@Override
		protected Boolean doInBackground(Integer... friendId) {
			CustomHttpClient request = new CustomHttpClient();
			JSONObject jObj = null;
			ArrayList<NameValuePair> param = new ArrayList<NameValuePair>();
			param.add(new BasicNameValuePair("userId", ""+pUserId));
			for (Integer fId : friendId) {
				param.add(new BasicNameValuePair("friendId[]", ""+fId));
			}

			try {
				jObj = request.postData("delFriend", param);

				if(jObj.getInt("back") != 0) {
					return false;
				}

			} catch (Exception e) {
				return false;
			}

			return true;
		}

		@Override
		protected void onPostExecute(final Boolean success) {
			mDel = null;
			if (mActivity.get() != null) {
				showProgress(false);
				if (!success) {
					Toast.makeText(mActivity.get(), "Une erreur est survenue.", Toast.LENGTH_LONG).show();
					return;
				}
				mActivity.get().refreshUserList();
			}
		}
		
		public void link(FriendListActivity pActivity) {
			mActivity = new WeakReference<FriendListActivity>(pActivity);
		}
	}

	@Override
	public void afterTextChanged(Editable arg0) {
		setAutocomplete(mAddFriendView.getText().toString());
	}

	@Override
	public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {}

	@Override
	public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {		
		setAutocomplete(mAddFriendView.getText().toString());
	}
	
	private void setAutocomplete(String input) {
		if(mListNameAutocompTask != null || input.length() < FriendListActivity.THRESHOLD) {
			return;
		}

		mListNameAutocompTask = new RefreshNameAutocompTask();
		mListNameAutocompTask.execute(input);
	}
	
	private class RefreshNameAutocompTask extends AsyncTask<String, Void, Boolean> {
		private List<String> lUserName = new ArrayList<String>();

		@Override
		protected Boolean doInBackground(String... params) {
			lUserName.clear();
			
			CustomHttpClient request = new CustomHttpClient();
			JSONObject jObj = null;
			ArrayList<NameValuePair> param = new ArrayList<NameValuePair>();
			param.add(new BasicNameValuePair("friendName", params[0]));

			try {
				jObj = request.postData("autoCompleteUserName", param);

				if(jObj.getInt("back") != 0) {
					return false;
				}
				
				JSONArray list = jObj.getJSONArray("list");
				for(int i=0; i<list.length(); i++) {
					lUserName.add(list.getString(i));
				}

			} catch (Exception e) {
				return false;
			}

			return true;
		}

		@Override
		protected void onPostExecute(final Boolean success) {
			if (success && lUserName.size() != 0) {

				autoCompleteAdapter.clear();
				for (String uName : lUserName) {
					autoCompleteAdapter.add(uName);
				}
				autoCompleteAdapter.notifyDataSetChanged();
				
			}
			mListNameAutocompTask = null;
		}
	}
	
	private class InviteFriendTask extends AsyncTask<Integer, Void, Boolean> {

		private WeakReference<FriendListActivity> mActivity = null;
		
		public InviteFriendTask(FriendListActivity pActivity) {
			link(pActivity);
		}
		
		@Override
		protected Boolean doInBackground(Integer... friendId) {
			CustomHttpClient request = new CustomHttpClient();
			JSONObject jObj = null;
			ArrayList<NameValuePair> param = new ArrayList<NameValuePair>();
			param.add(new BasicNameValuePair("eventId", ""+selectedEvent));
			for (Integer fId : friendId) {
				param.add(new BasicNameValuePair("friendId[]", ""+fId));
			}

			try {
				jObj = request.postData("inviteForEvent", param);

				if(jObj.getInt("back") != 0) {
					return false;
				}

			} catch (Exception e) {
				return false;
			}

			return true;
		}

		@Override
		protected void onPostExecute(final Boolean success) {
			mInvite = null;
			if (mActivity.get() != null) {
				showProgress(false);
				if (!success) {
					Toast.makeText(mActivity.get(), "Une erreur est survenue.", Toast.LENGTH_LONG).show();
					return;
				}
				FriendListActivity.this.finish();
			}
		}
		
		public void link(FriendListActivity pActivity) {
			mActivity = new WeakReference<FriendListActivity>(pActivity);
		}
	}
}
